#pragma once
#include "Log.hpp"
#include <cerrno>
#include <cstdint>
#include <cstdlib>
#include<iostream>
#include<cstring>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>

class Sock
{
public:
    Sock(){}
    int Socket()
    {
        int serversock=socket(AF_INET, SOCK_DGRAM, 0);
        if(serversock < 0)
        {
            logMessage(FATAL, "%d:%s",errno, strerror(errno));
            exit(-1);
        }
        std::cout<<"create socket finished"<<std::endl;
        return serversock;
    }
    // void Bind(int sock,uint16_t port,std::string ip="0.0.0.0")
    // {
    //     struct sockaddr_in server;
    //     socklen_t len=sizeof(server);
    //     memset(&server, 0, sizeof(server));
    //     server.sin_port=htons(port);
    //     server.sin_family=AF_INET;
    //     inet_pton(AF_INET, ip.c_str(), &server.sin_addr);
    //     //server.sin_addr.s_addr=inet_addr(ip.c_str());
    //     if(bind(sock, (struct sockaddr*)&server, len) < 0)
    //     {
    //         //logMessage(int level, const char *format, ...)
    //         exit(-1);
    //     }
    // }
    void Bind(int sock,uint16_t port,std::string ip)
    {
        struct sockaddr_in server;
        socklen_t len=sizeof(server);
        memset(&server,0,sizeof(server));
        server.sin_family=AF_INET;
        server.sin_port=htons(port);
        inet_pton(AF_INET, ip.c_str(),&server.sin_addr);
        if(bind(sock,(struct sockaddr*)&server,len) < 0)
        {
            //logMessage(int level, const char *format, ...)
            exit(-1);
        }
    }
    void Listen(int sock)
    {
        if(listen(sock, gbacklog) < 0)
        {
            //logMessage(int level, const char *format, ...)
            exit(-1);
        }
        //logMessage(int level, const char *format, ...)
    }
    // int Accept(int sock,uint16_t* port,std::string* ip)
    // {
    //     //这里的输出型参数得到参数以后还要传给外部函数使用
    //     struct sockaddr_in client;
    //     socklen_t len=sizeof(client);
    //     int serversock=accept(sock, (struct sockaddr*)&client, &len);
    //     if(serversock < 0)
    //     {
    //         //logMessage(int level, const char *format, ...)
    //         exit(-1);
    //     }
    //     if(port){
    //         *port=ntohs(client.sin_port);
    //     }
    //     if(ip){
    //         *ip=inet_ntoa(client.sin_addr);
    //     }
    //     return serversock;
    // }
    int Accept(int sock,uint16_t* port,std::string* ip)
    {
        struct sockaddr_in client;
        socklen_t len=sizeof(client);
        int serversock=accept(sock, (struct sockaddr*)&client, &len);
        if(serversock < 0)
        {
            //logMessage(int level, const char *format, ...)
            exit(-1);
        }
        if(port){
            *port=ntohs(client.sin_port);
        }
        if(ip){
           *ip=inet_ntoa(client.sin_addr); 
        }
        return serversock;
    }
    // bool Connet(int sock,uint16_t& port,std::string& ip)
    // {
    //     struct sockaddr_in server;
    //     socklen_t len=sizeof(server);
    //     bzero(&server,sizeof(server));
    //     server.sin_family=AF_INET;
    //     server.sin_port=htons(port);
    //     server.sin_addr.s_addr=inet_pton(AF_INET, ip.c_str(), &server.sin_addr);
    //     if(connect(sock, (struct sockaddr*)&server, len) < 0)
    //     {
    //         //logMessage(int level, const char *format, ...)
    //         return false;
    //     }
    //     else{
    //         return true;
    //     }
    // }
    bool Connet(int sock,uint16_t& port,std::string& ip)
    {
        struct sockaddr_in server;
        socklen_t len=sizeof(server);
        bzero(&server,sizeof(server));
        server.sin_family=AF_INET;
        server.sin_port=htons(port);
        server.sin_addr.s_addr=inet_pton(AF_INET, ip.c_str(), &server.sin_addr);
        int ret=connect(sock, (struct sockaddr*)&server, len);
        if(ret == 0){
            return true;
        }
        else{
            return false;
        }
    }
private:
    const int gbacklog=20;
};
